/**
 *  ==== 自己动手实现 Promise ======
 */

const PENDING = 'PENDING' //默认是等待态
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

// 我们还需要考虑,这个 x 可能是别人家的promise
// 因为我们希望 我的 promise 可以兼容别人的promise
function resolvePromise(x, promise2, resolve, reject) {
  // 如果 x是 一个普通值, 则直接调用 resolve 即可
  if (x === promise2) {
    return reject(new TypeError("循环应用"))
  }

  // 继续判断 x 是不是一个 promise. promise需要有一个 then方法
  if ((typeof x === "object" && x != null) || (typeof x == "function")) {
    // 才有可能是 promise, 继续判断 x 是否有then
    let called = false;
    try {
      let then = x.then
      if (typeof then == "function") { // 认为它是promise
        then.call(x, (y) => { // y 有可能还是一个promise, 所以要再次进行解析流程
          if (called) return
          called = true;
          // 我需要不停的解析成功的promise中返回的成功值, 知道这个值是一个普通值.
          resolvePromise(y, promise2, resolve, reject)
        }, (r) => {
          if (called) return
          called = true;
          reject(r)
        })
      } else { // {then:1}
        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true;
      reject(e)  // 让promise2 变成失败态
    }
  } else {
    //x 是一个普通值
    resolve(x)
  }

  // 如果 x 是一个promise, 那么采用这个 promise 的状态, 决定调用的是 resolve还是reject

}

class Promise {

  constructor(executor) {
    this.status = PENDING
    this.value = undefined;
    this.reason = undefined
    this.onResolvedCallbacks = []
    this.onRejectedCallbacks = []


    const resolve = (value) => {
      if (value instanceof Promise) { // 这个方法并不属于规范中的,只是为了和原生的promise表现一样
        return value.then(resolve, reject)
      }
      if (this.status == PENDING) {
        this.value = value;
        this.status = FULFILLED
        this.onResolvedCallbacks.forEach((fn) => fn())
      }
    }
    const reject = (reason) => {
      if (this.status == PENDING) {
        this.reason = reason
        this.status = REJECTED
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }

    try {
      executor(resolve, reject)
    } catch (e) {
      reject(e)
    }

  }


  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled == "function" ? onFulfilled : v => v
    onRejected = typeof onRejected == "function" ? onRejected : e => {
      throw  e
    }
    // 每次调用 then 方法都必须返回一个全新的 promise
    let promise2 = new Promise((resolve, reject) => {
      if (this.status == FULFILLED) {
        setTimeout(() => {
          try {
            // x 就是上一个 then成功或者失败的返回值, 这个 x决定promise2 走成功还是失败的回调
            let x = onFulfilled(this.value)
            resolvePromise(x, promise2, resolve, reject)
            // resolve(x)
          } catch (e) {
            reject(e)
          }
        }, 0)
      }

      if (this.status == REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(x, promise2, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      }
      if (this.status == PENDING) {
        // 发布订阅模式
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })
    return promise2
  }

  catch(errFn) {
    return this.then(null, errFn)
  }

  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value)
    })
  }

  static reject(err) {
    return new Promise((resolve, reject) => {
      reject(err)

    })
  }
}

Promise.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd
}

module.exports = Promise
